/**
 * Written by Timbot
 * V1.0, June 2007
 */
package com.as3.timbot.net
{
	import flash.events.EventDispatcher;
	import flash.display.Sprite;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLStream;
	import flash.net.URLLoaderDataFormat;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	
	import com.as3.timbot.utils.zip.ZipFile;
	import com.as3.timbot.utils.zip.ZipEntry;
	import com.as3.timbot.net.LoadEvent;
	import com.as3.timbot.net.ILoader;
	import com.as3.timbot.command.AbstractCommand;
	import com.as3.timbot.command.CommandEvent;
	
	public class AbstractLoader extends AbstractCommand implements ILoader
	{
		private var __loader:URLStream;
		private var __request:URLRequest;
		private var __bytes:ByteArray;
		private var __URL:String;
		private var __endian:String;
		private var __zipped:Boolean;
		private var __closeByte:uint;
		private var __closeStream:Boolean;
		
		/**
		*	Defines basic functionality for loading any assets into flash.  All assets are loaded in binary form, then cast to types by 
		*	the sub-classes of this one
		* 
		*	@param _url The path to the asset to be loaded
		*
		*	@param _zipped Whether the asset is in zipped form
		*
		* 	@langversion ActionScript 3.0
		*	@playerversion Flash 9.0
		*	@tiptext
		*/
		public function AbstractLoader(_url:String, _zipped:Boolean)
		{
			super();
			__closeStream = false;
			__zipped = _zipped;
			if(__zipped){
				setEndian(Endian.LITTLE_ENDIAN);
			}
			init(_url);
		}
		private function init(_value:String):void
		{
			__bytes = new ByteArray();
			setURLTo(_value);
			
		}
		/**
		*	Begins the load of the requested asset, previously set by setURLTo method
		*
		* 	@langversion ActionScript 3.0
		*	@playerversion Flash 9.0
		*	@tiptext
		*/
		public function loadAsset():void
		{
			///could this be replaced with a RangeFinder instance?...............t.w.
			super.begin();
			__loader = new URLStream();
			__request = new URLRequest(__URL);
			__loader.addEventListener(Event.COMPLETE, loadHandler);
			__loader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
			__loader.load(__request);
		}
		///////////////////////////for command purposes/////////////////////////////
		override public function execute():void
		{
			loadAsset();
		}
		///////////////////////////////////////////////////////////////////////////
		private function setURLTo(_value:String):void
		{
			__URL = _value;
		}
		private function progressHandler(ev:ProgressEvent):void
		{
			//fire off a command progress event..............t.w.
			
			//we can close the stream any time we wish, closeByte set by subclass strategy........t.w.
			if(__closeByte){
				progress(ev.bytesLoaded/__closeByte*100);
				if(ev.bytesLoaded>__closeByte){
					__loader.removeEventListener(ProgressEvent.PROGRESS,progressHandler);
					__closeStream = true;
					loadHandler(ev);
				}
				
			}else{
				progress(ev.bytesLoaded/ev.bytesTotal*100);
			}
			
		}
		private function loadHandler(ev:Event):void
		{
			if(__endian){
				__bytes.endian = __endian;
			};
			ev.target.readBytes(__bytes);
			if(__zipped){
				var myZipFile:ZipFile = new ZipFile(__bytes);
				var unzippedBytes:ByteArray = myZipFile.getInput(myZipFile.entries[0]);
				castType(unzippedBytes);
			}else{
				if(__closeStream){__loader.close()};
				castType(__bytes);
			};
			//__bytes is now a byte array, and could be anything...depending what we cast it to
			
		}
		public function setCloseByte(value:uint):void
		{
			__closeByte = value;
		}
		protected function setEndian(value:String):void
		{
			__endian = value;
		}
		protected function castType(_bytes:ByteArray):void
		{
			
		}
		/**
		*	Called after the casting is completed in the sub-class
		* 
		*	@param value The results of the casting operation
		*
		* 	@langversion ActionScript 3.0
		*	@playerversion Flash 9.0
		*	@tiptext
		*/
		public function castComplete(value:*):void
		{
			///fire off a command complete event..........................t.w.
			var myEvent:LoadEvent = new LoadEvent(LoadEvent.LOADCOMPLETE);
			myEvent.setContent(value);//if i want to make this Command-compatible, i should fire a command event here
			super.fireEventType(myEvent);
			super.end();
			//fire off a special completed event in here, the loading and casting is done....t.w.
		}
		
	}
}